import { useCallback, useEffect, useMemo, useState } from 'react'
import { DndProvider } from 'react-dnd'
import { HTML5Backend } from 'react-dnd-html5-backend'
import PropTypes from 'prop-types'

import PropertyPanel from './layout/PropertyPanel'
import PalettePanel from './layout/PalettePanel'
import MiddlePanel from './layout/MiddlePanel'

import inputMap, { baseProperties, baseInputProps, formProperties } from './inputMap'
import { createOneFromIndex, deepClone, exChangePosition } from '../../utils/array'
import { generateRandomNumber } from '../../utils'
import './index.css'

const FormDesigner = ({
  value = {},
  onChange
}) => {

  // 当前锁定的表单
  const [focusItem, setFocusItem] = useState(null)

  // 表单的基本信息
  const baseInfo = useMemo(() => {
    const {
      formItems,
      ...baseInfo
    } = value
    return baseInfo
  }, [value])

  // 给请求过来的数据加上 id
  const formItemsWithId = useMemo(() => {
    return value.formItems ? value.formItems.map(el => ({
      id: el.id || generateRandomNumber(6),
      ...el
    })) : []
  }, [value])

  // 当前表单发生变化 修改属性表单
  useEffect(() => {
  }, [focusItem])

  // 修改锁定表单
  const handleChangefocusItem = (item) => {
    if (!item) {
      setFocusItem(null)
    } else {
      setFocusItem(item)
    }
  }

  // 新建一条数据
  const createNewFormItem = (inputType) => {
    const formItem = inputMap[inputType]
    const id = generateRandomNumber(6)
    return {
      id: id,
      type: inputType,
      name: inputType + '-' + id,
      label: formItem.name,
      required: false,
      inputProps: {}
    }
  }

  // 拖拽创建
  const handleCreateItem = (inputType, insertIndex) => {
    const newItem = createNewFormItem(inputType)
    let _formItems = JSON.parse(JSON.stringify(formItemsWithId))
    _formItems.splice(insertIndex, 0, newItem)
    onChange({
      ...baseInfo,
      formItems: _formItems
    })
    setFocusItem(newItem)
  }

  // 删除
  const handleDeleteItem = (item) => {
    const _formItems = formItemsWithId.filter(el => el.id !== item.id)
    onChange({
      ...baseInfo,
      formItems: _formItems
    })
    if (item.id === focusItem.id) {
      setFocusItem(null)
    }
  }

  // 复制
  const handleCopyItem = (index) => {
    const newFormItem = deepClone(formItemsWithId[index])
    newFormItem.id = generateRandomNumber(6)
    newFormItem.name = newFormItem.type + newFormItem.id
    onChange({
      ...baseInfo,
      formItems: createOneFromIndex(formItemsWithId, newFormItem, index)
    })
    setFocusItem(newFormItem)
  }

  // 修改属性
  const handleModifyItem = useCallback((type, values) => {
    if (focusItem === null) {
      onChange({
        ...baseInfo,
        ...values,
        formItems: formItemsWithId
      })
    } else {
      let newValue
      if (type === 'base') {
        newValue = formItemsWithId.map(el => {
          if (el.id === focusItem.id) {
            return {
              ...el,
              ...values
            }
          } else {
            return el
          }
        })
      } else if (type === 'input') {
        newValue = formItemsWithId.map(el => {
          if (el.id === focusItem.id) {
            return {
              ...el,
              inputProps: {
                ...el.inputProps,
                ...values
              }
            }
          } else {
            return el
          }
        })
      }
      onChange({
        ...baseInfo,
        formItems: newValue
      })
    }
  }, [focusItem])

  // 拖拽排序
  const handleMoveItem = (fromIndex, toIndex) => {
    onChange({
      ...baseInfo,
      formItems: exChangePosition(formItemsWithId, fromIndex, toIndex)
    })
  }

  const handleAction = (action) => {
    switch (action.type) {
      case 'create':
        handleCreateItem(action.paletteItem, action.insertIndex)
        break;
      case 'delete':
        handleDeleteItem(action.item)
        break;
      case 'modify':
        handleModifyItem()
        break;
      case 'move':
        handleMoveItem(action.fromIndex, action.toIndex)
        break;
      case 'copy':
        handleCopyItem(action.index)
        break;
      case 'focus':
        handleChangefocusItem(action.item)
        break;
    }
  }

  // 属性面板的表单的设置
  const properPanelFormItems = useMemo(() => {
    if (focusItem) {
      const type = focusItem?.type || 'text'
      const inputProperties = baseInputProps.concat(inputMap[type].props)
      baseProperties.forEach((el) => {
        if (el.name === 'defaultValue') {
          el.type = type
          el.inputProps = focusItem.inputProps
        }
      })
      return {
        base: baseProperties,
        input: inputProperties
      }
    } else {
      return {
        base: formProperties
      }
    }
  }, [focusItem])

  // 属性面板的表单的值
  const properPanelFormValues = useMemo(() => {
    return focusItem ? focusItem : baseInfo
  }, [focusItem])


  return <DndProvider backend={HTML5Backend}>
    <div className="form-designer-box">
      <div className="form-designer-left">
        <PalettePanel></PalettePanel>
      </div>
      <div className="form-designer-center">
        <MiddlePanel
          items={formItemsWithId}
          focusItem={focusItem}
          onAction={handleAction}
        ></MiddlePanel>
      </div>
      <div className="form-designer-right">
        <PropertyPanel
          formItems={properPanelFormItems}
          initValues={properPanelFormValues}
          onValuesChange={handleModifyItem}
        ></PropertyPanel>
      </div>
    </div>
  </DndProvider>
}

FormDesigner.propTypes = {
  value: PropTypes.object,
  onChange: PropTypes.func
}

export default FormDesigner